---
title: Tutorial - Esteso con le Collezioni di Contenuti
description: >-
  Converti la guida Build a Blog da routing basato su file a collezioni di contenuti.
i18nReady: true
---
import PackageManagerTabs from '~/components/tabs/PackageManagerTabs.astro';
import Box from '~/components/tutorial/Box.astro';
import MultipleChoice from '~/components/tutorial/MultipleChoice.astro';
import PreCheck from '~/components/tutorial/PreCheck.astro';
import Option from '~/components/tutorial/Option.astro';
import { Steps } from '@astrojs/starlight/components';

Le **collezioni di contenuto** sono un modo potente per gestire gruppi di contenuti simili, come i post del blog. Le collezioni aiutano ad organizzare i tuoi documenti, a convalidare il tuo frontmatter YAML e a fornire automaticamente la sicurezza del tipo TypeScript per tutti i tuoi contenuti (anche se non scrivi alcun TypeScript tu stesso).

<PreCheck>
  - Sposta la tua cartella di post del blog in `src/content/`
  - Crea uno schema per definire il tuo frontmatter dei post del blog
  - Usa `getCollection()` per ottenere contenuti e metadati dei post del blog
</PreCheck>

## Prerequisiti

Avrai bisogno di **un progetto Astro esistente con file Markdown o MDX nella cartella `src/pages/`**.

Questo tutorial usa il [progetto finito della guida Build a Blog](https://github.com/withastro/blog-tutorial-demo) per dimostrare come convertire un blog in collezioni di contenuti. Puoi fare il fork e usare quella base di codice in locale, o completare il tutorial nel browser [modificando il codice della guida al blog in StackBlitz](https://stackblitz.com/github/withastro/blog-tutorial-demo/tree/complete?file=src%2Fpages%2Findex.astro).

Puoi invece seguire questi passaggi con il tuo progetto Astro, ma dovrai adattare le istruzioni alla tua base di codice.

Ti consigliamo di utilizzare il nostro progetto di esempio per completare prima questo breve tutorial. Poi, puoi usare ciò che hai imparato per creare collezioni di contenuti nel tuo progetto.

## Codice Tutorial per Creare un Blog

Nella [guida introduttiva Build a Blog](/it/tutorial/0-introduction/), hai imparato il routing basato su file integrato di Astro: qualsiasi file `.astro`, `.md` o `.mdx` ovunque nella cartella `src/pages/` diventava automaticamente una pagina del tuo sito.

Per creare il tuo primo post sul blog su `https://example.com/posts/post-1/`, hai creato una cartella `/posts/` e aggiunto il file `post-1.md`. Poi hai aggiunto un nuovo file Markdown a questa cartella ogni volta che volevi aggiungere un nuovo post al tuo sito.


## Pagine Vs Collezioni

Anche quando stai usando le collezioni di contenuti, userai ancora la cartella `src/pages/` per le pagine individuali, come la tua pagina About Me. Ma, spostando i tuoi post del blog nella cartella speciale `src/content/` ti permetterà di usare API più potenti e performanti per generare l'indice dei post del blog e visualizzare i tuoi post del blog individuali.

Allo stesso tempo, riceverai una migliore guida e autocompletamento nel tuo editor di codice perché avrai uno **[schema](/it/guides/content-collections/#defining-a-collection-schema)** per definire una struttura comune per ogni post che Astro ti aiuterà ad applicare. Nel tuo schema, puoi specificare quando le proprietà del frontmatter sono richieste, come una descrizione o un autore, e quale tipo di dati deve essere ogni proprietà, come una stringa o un array. Questo porta a cogliere molti errori prima, con messaggi di errore descrittivi che ti dicono esattamente qual è il problema.

Leggi di più sulle [collezioni di contenuti di Astro](/it/guides/content-collections/) nella nostra guida, o inizia con le istruzioni qui sotto per convertire un blog di base da `src/pages/posts/` a `src/content/posts/`.

<Box icon="question-mark">
### Testa la tua conoscenza

1. Quale pagina dovresti tenere in `src/pages/`?

    <MultipleChoice>
      <Option>
        I post del blog che contengono tutti la stessa struttura di base e i metadati
      </Option>
      <Option>
        Le pagine dei prodotti in un sito di eCommerce
      </Option>
      <Option isCorrect>
        Una pagina di contatto, perché non hai più pagine simili di questo tipo
      </Option>
    </MultipleChoice>

2. Quale **non** è un vantaggio dello spostamento dei post del blog in una collezione di contenuti?

    <MultipleChoice>
      <Option isCorrect>
         Le pagina sono create automaticamente per ogni file
      </Option>
      <Option>
        Migliori messaggi di errore, perché Astro conosce meglio ogni file
      </Option>
      <Option>
        Miglior recupero dei dati, con una funzione più performante
      </Option>
    </MultipleChoice>

3. Le collezioni di contenuto usano TypeScript per...
    <MultipleChoice>
      <Option>
        Per farmi sentire male
      </Option>
      <Option isCorrect>
        Per capire il mio progetto, anche se non scrivo alcun TypeScript
      </Option>
      <Option>
        Solo se ho impostato la configurazione `strict` o `strictest`
      </Option>
    </MultipleChoice>

</Box>

## Estendere il blog di tutorial con le collezioni di contenuti

Gli step seguenti mostrano come estendere il prodotto finale della guida Build a Blog creando una collezione di contenuti per i post del blog.

### Aggiorna le dipendenze

<Steps>
1. Aggiorna all'ultima versione di Astro, e aggiorna tutte le integrazioni alle loro ultime versioni eseguendo i seguenti comandi nel tuo terminale:

    <PackageManagerTabs>
      <Fragment slot="npm">
      ```shell
      # Upgrade to Astro v4.x
      npm install astro@latest

      # Example: upgrade the blog tutorial Preact integration
      npm install @astrojs/preact@latest
      ```
      </Fragment>
      <Fragment slot="pnpm">
      ```shell
      # Upgrade to Astro v4.x
      pnpm add astro@latest

    # Example: upgrade the blog tutorial Preact integration
      pnpm add @astrojs/preact@latest
      ```
      </Fragment>
      <Fragment slot="yarn">
      ```shell
      # Upgrade to Astro v4.x
      yarn add astro@latest

    # Example: upgrade the blog tutorial Preact integration
      yarn add @astrojs/preact@latest
      ```
      </Fragment>
    </PackageManagerTabs>

    :::tip
    Se stai usando un tuo progetto, assicurati di aggiornare tutte le dipendenze che hai installato. Il codice di esempio della guida al blog usa solo l'integrazione Preact.
    :::

2. Il blog di tutorial usa l'impostazione TypeScript `base` (meno rigorosa). Per usare le collezioni di contenuto, devi [configurare TypeScript](/it/guides/content-collections/#setting-up-typescript) per le collezioni di contenuto **o** usando l'impostazione `strict` o `strictest`, **o** aggiungendo due opzioni in `tsconfig.json`.

    Per usare le collezioni di contenuto senza scrivere TypeScript nel resto dell'esempio della guida al blog, aggiungi le seguenti due opzioni di configurazione TypeScript al file di configurazione:

    ```json title="tsconfig.json" ins={5,6}
    {
      // Note: Non devi cambiare niente se usi "astro/tsconfigs/strict" o "astro/tsconfigs/strictest"
      "extends": "astro/tsconfigs/base",
      "compilerOptions": {
        "strictNullChecks": true,
        "allowJs": true
      }
    }
    ```
</Steps>

### Crea una collezione per i post del tuo blog

<Steps>
3. Crea una nuova **collezione** (cartella) chiamata `src/content/posts/`.

4. Sposta tutti i tuoi post del blog esistenti (file `.md`) da `src/pages/posts/` in questa nuova collezione.

5. Crea un file `src/content/config.ts` per [definire uno schema](/it/guides/content-collections/#defining-a-collection-schema) per la tua `postsCollection`. Per il codice esistente della guida al blog, aggiungi il seguente contenuto al file per definire tutte le proprietà del frontmatter usate nei post del blog:

    ```ts title="src/content/config.ts"
    // Import utilities from `astro:content`
    import { z, defineCollection } from "astro:content";
    // Definisci un `type` e uno `schema` per ogni collezione
    const postsCollection = defineCollection({
        type: 'content',
        schema: z.object({
          title: z.string(),
          pubDate: z.date(),
          description: z.string(),
          author: z.string(),
          image: z.object({
            url: z.string(),
            alt: z.string()
          }),
          tags: z.array(z.string())
        })
    });
    // Esporta un singolo oggetto `collections` per registrare la tua collezione
    export const collections = {
      posts: postsCollection,
    };
    ```

6. Per consentire ad Astro di riconoscere il tuo schema, interrompi il server di sviluppo (`CTRL + C`) e esegui il seguente comando: [`npx astro sync`](/it/reference/cli-reference/#astro-sync). Questo definirà il modulo `astro:content` per l'API delle Collezioni di Contenuti. Riavvia il server di sviluppo per continuare con il tutorial.
</Steps>

### Genera le pagine da una collezione

<Steps>
7. Crea un file per la pagina chiamato `src/pages/posts/[...slug].astro`. I tuoi file Markdown e MDX non diventano più automaticamente pagine usando il routing basato su file di Astro quando sono all'interno di una collezione, quindi devi creare una pagina responsabile per generare ogni singolo post del blog.

8. Aggiungi il codice seguente per [interrogare la tua collezione](/it/guides/content-collections/#querying-collections) per rendere disponibile a ogni pagina che genererà lo slug e il contenuto della pagina di ogni post del blog:

    ```astro title="src/pages/posts/[...slug].astro"
    ---
    import { getCollection } from 'astro:content';
    import MarkdownPostLayout from '../../layouts/MarkdownPostLayout.astro';

    export async function getStaticPaths() {
      const blogEntries = await getCollection('posts');
      return blogEntries.map(entry => ({
        params: { slug: entry.slug }, props: { entry },
      }));
    }

    const { entry } = Astro.props;
    const { Content } = await entry.render();
    ---
    ```

9. Renderizza il tuo `<Content />` del post all'interno del layout per le pagine Markdown. Questo ti permette di specificare un layout comune per tutti i tuoi post.

    ```astro title="src/pages/posts/[...slug].astro" ins={15-17}
    ---
    import { getCollection } from 'astro:content';
    import MarkdownPostLayout from '../../layouts/MarkdownPostLayout.astro';

    export async function getStaticPaths() {
      const blogEntries = await getCollection('posts');
      return blogEntries.map(entry => ({
        params: { slug: entry.slug }, props: { entry },
      }));
    }

    const { entry } = Astro.props;
    const { Content } = await entry.render();
    ---
    <MarkdownPostLayout frontmatter={entry.data}>
      <Content />
    </MarkdownPostLayout>
    ```

10. Rimuovi la definizione `layout` nel frontmatter di ogni singolo post. Il tuo contenuto è ora racchiuso in un layout quando viene renderizzato, e questa proprietà non è più necessaria.

    ```md title="src/content/posts/post-1.md" del={2}
    ---
    layout: ../../layouts/MarkdownPostLayout.astro
    title: 'My First Blog Post'
    pubDate: 2022-07-01
    ...
    ---
    ```
</Steps>

### Rimpiazza `Astro.glob()` con `getCollection()`

<Steps>
11. Ovunque tu abbia una lista di post del blog, come la pagina Blog della guida (`src/pages/blog.astro/`), dovrai sostituire `Astro.glob()` con [`getCollection()`](/it/reference/api-reference/#getcollection) come modo per recuperare contenuti e metadati dai tuoi file Markdown.

    ```astro title="src/pages/blog.astro" "post.data" "getCollection(\"posts\")" "/posts/${post.slug}/" del={7} ins={2,8}
    ---
    import { getCollection } from "astro:content";
    import BaseLayout from "../layouts/BaseLayout.astro";
    import BlogPost from "../components/BlogPost.astro";

    const pageTitle = "My Astro Learning Blog";
    const allPosts = await Astro.glob("../pages/posts/*.md");
    const allPosts = await getCollection("posts");
    ---
    ```

12. Dovrai anche aggiornare i riferimenti ai dati restituiti per ogni `post`. Ora troverai i valori del frontmatter sulla proprietà `data` di ogni oggetto. Inoltre, quando si usano le collezioni, ogni oggetto `post` avrà uno `slug` di pagina, non un URL completo.

    ```astro title="src/pages/blog.astro" "data" "/posts/$\{post.slug\}/" del={14} ins={15}
    ---
    import { getCollection } from "astro:content";
    import BaseLayout from "../layouts/BaseLayout.astro";
    import BlogPost from "../components/BlogPost.astro";

    const pageTitle = "My Astro Learning Blog";
    const allPosts = await getCollection("posts");
    ---
    <BaseLayout pageTitle={pageTitle}>
      <p>This is where I will post about my journey learning Astro.</p>
      <ul>
        {
          allPosts.map((post) => (
            <BlogPost url={post.url} title={post.frontmatter.title} />)}
            <BlogPost url={`/posts/${post.slug}/`} title={post.data.title} />
          ))
        }
      </ul>
    </BaseLayout> 
    ```

13. Il blog di tutorial genera anche dinamicamente una pagina per ogni tag usando `src/pages/tags/[tag].astro` e visualizza un elenco di tag su `src/pages/tags/index.astro`.
   
          Applica gli stessi cambiamenti di cui sopra a questi due file:
      
          - recupera i dati per tutti i posts del tuo blog usando `getCollection("posts")` invece di `Astro.glob()`
          - accedi a tutti i valori di frontmatter usando `data` invece di `frontmatter`
          - crea un URL della pagina aggiungendo lo `slug` del post al percorso `/posts/`
        
        La pagina che genera individualmente le pagine dei tag diventa ora:

        ```astro title="src/pages/tags/[tag].astro" "post.data.tags" "getCollection(\"posts\")" "post.data.title" ins={2} "/posts/${post.slug}/"
        ---
        import { getCollection } from "astro:content";
        import BaseLayout from "../../layouts/BaseLayout.astro";
        import BlogPost from "../../components/BlogPost.astro";

        export async function getStaticPaths() {
          const allPosts = await getCollection("posts");
          const uniqueTags = [...new Set(allPosts.map((post) => post.data.tags).flat())];

          return uniqueTags.map((tag) => {
            const filteredPosts = allPosts.filter((post) =>
              post.data.tags.includes(tag)
            );
            return {
              params: { tag },
              props: { posts: filteredPosts },
            };
          });
        }
        
        const { tag } = Astro.params;
        const { posts } = Astro.props;
        ---

        <BaseLayout pageTitle={tag}>
          <p>Posts tagged with {tag}</p>
          <ul>
            { posts.map((post) => <BlogPost url={`/posts/${post.slug}/`} title={post.data.title} />) }
          </ul>
        </BaseLayout>
        ```

        <Box icon="puzzle-piece">
          ### Prova tu - Aggiorna la query nella pagina dell'indice dei tag

          Importa e usa `getCollection` per recuperare i tag usati nei post del blog su `src/pages/tags/index.astro`, seguendo gli [stessi passaggi di cui sopra](#rimpiazza-astroglob-con-getcollection).

          <details>
          <summary>Mostrami il codice.</summary>
          ```astro title="src/pages/tags/index.astro" "post.data" "getCollection(\"posts\")" ins={2}
          ---
          import { getCollection } from "astro:content";
          import BaseLayout from "../../layouts/BaseLayout.astro";     
          const allPosts = await getCollection("posts");
          const tags = [...new Set(allPosts.map((post) => post.data.tags).flat())];
          const pageTitle = "Tag Index";
          ---
          ...
          ```
          </details>
      </Box>
</Steps>

### Aggiorna ogni valore di frontmatter per corrispondere allo schema

<Steps>
14. Se necessario, aggiorna qualunque valore del frontmatter in tutto il tuo progetto, come nel tuo layout, che non corrisponde allo schema delle collezioni.

    Nel blog di esempio, `pubDate` era una stringa. Ora, secondo lo schema che definisce i tipi per il frontmatter del post, `pubDate` sarà un
    oggetto `Date`.
    
    Per renderizzare la data nel layout del post del blog, convertila in una stringa:

    ```astro title="src/layouts/MarkdownPostLayout.astro" ins="toString()"
    ...
    <BaseLayout pageTitle={frontmatter.title}>
      <p>{frontmatter.pubDate.toString().slice(0,10)}</p>
      <p><em>{frontmatter.description}</em></p>
      <p>Written by: {frontmatter.author}</p>
      <img src={frontmatter.image.url} width="300" alt={frontmatter.image.alt} />
    ...
    ```
</Steps>

### Aggiorna la funzione RSS

<Steps>
15. Per ultima cosa, il progetto di blog tutorial include un feed RSS. Questa funzione deve anche usare `getCollection()` per restituire informazioni dai tuoi post del blog. Poi genererai gli elementi RSS usando l'oggetto `data` restituito.

    ```js title="src/pages/rss.xml.js" del={2,11} ins={3,6,12-17}
    import rss from '@astrojs/rss';
    import { pagesGlobToRssItems } from '@astrojs/rss';
    import { getCollection } from 'astro:content';

    export async function GET(context) {
      const posts = await getCollection("posts");
      return rss({
        title: 'Astro Learner | Blog',
        description: 'My journey learning Astro',
        site: context.site,
        items: await pagesGlobToRssItems(import.meta.glob('./**/*.md')),
        items: posts.map((post) => ({
          title: post.data.title,
          pubDate: post.data.pubDate,
          description: post.data.description,
          link: `/posts/${post.slug}/`,
        })),
        customData: `<language>en-us</language>`,
      })
    }
    ```
</Steps>

Per l'esempio completo della guida al blog usando le collezioni di contenuto, vedi il [branch Content Collections](https://github.com/withastro/blog-tutorial-demo/tree/content-collections) del repo della guida.
